//---HEADER
//	Name:	Types.hpp
//	Desc:	Common types and macros
//------------------------------>
#include <RSLib/Common.hpp>
#ifndef RSLIB___TYPES_HPP
#define RSLIB___TYPES_HPP
 
 
 
//---INCLUDE
//	<new>	- for in-place new
//------------------------->
#include <new>
 
 
 
//---TYPES
//	Note: These types should have been inside a Type namespace. However they have been declared in
//			the root namespace to be easily usable from RSLib headers. In fact VC7 (don't know others) 
//			doesn't support using namespace declarations inside classes as in the following example:
//
//			class SomeClass
//			{
//				using namespace RSLib::Type;
//				...
//			};
//
//			forcing the RSLib:: prefix to be used on every class outside the RSLib namespace.
//			RSLib client code can use the short-named aliases in the global namespace defined below.
//----------------------------------------------------------------------------------------------->
namespace RSLib{

typedef bool						Boolean;

typedef char						Char8;

#if defined(RSLIB___VC6_COMPILER)
	#define __wchar_t wchar_t
#endif
typedef __wchar_t					Char16;

typedef signed char				Integer8;
typedef signed short				Integer16;
typedef signed int				Integer32;

#if defined(RSLIB___VC6_COMPILER)
	typedef signed __int64		Integer64;	//VC6 doesn't support "long long"
#else
	typedef signed long long	Integer64;
#endif

typedef unsigned char			Unsigned8,	Byte;
typedef unsigned short			Unsigned16,	Word;
typedef unsigned int				Unsigned32,	DoubleWord, Dword;

#if defined(RSLIB___VC6_COMPILER)
	typedef unsigned __int64		Unsigned64,	QuadWord, Qword;	//VC6 doesn't support "long long"
#else
	typedef unsigned long long		Unsigned64,	QuadWord, Qword;
#endif

typedef float						Float32;
typedef double						Float64;

typedef void						Void;
typedef void*						Pointer;
 
 
typedef size_t						LargerUnsigned;
#if defined(RSLIB___64BITS)
	typedef Integer64				LargerInteger;
//	typedef Unsigned64			LargerUnsigned;
#elif defined(RSLIB___32BITS)
	typedef Integer32				LargerInteger;
//	typedef Unsigned32			LargerUnsigned;
#endif




//---UTILITY
//	Desc: see variable as belonging to a different type
//----------------------------------------------------> 
template<class T,class O> inline T& SeeAs(O& o){return *(T*)&o;}
 
 
 
}//namespace RSLib
 
 
 
//---TYPES
//	Desc: global aliases for types. To be used from clients of RSLib, 
//			since RSLib headers have direct access to long named types
//------------------------------------------------------------------>
#ifndef RSLIB___DONT_USE_GLOBAL_ALIASES_FOR_TYPES
typedef RSLib::Char8		char8;
typedef RSLib::Char16	char16;

typedef RSLib::Integer8		int8;
typedef RSLib::Integer16	int16;
typedef RSLib::Integer32	int32;
typedef RSLib::Integer64	int64;

typedef RSLib::Unsigned8	uint8;
typedef RSLib::Unsigned16	uint16;
typedef RSLib::Unsigned32	uint32;
typedef RSLib::Unsigned64	uint64;

typedef RSLib::Float32		flt32;
typedef RSLib::Float64		flt64;

typedef RSLib::LargerInteger	large_int;
typedef RSLib::LargerUnsigned large_uint;
#endif
 
 
 
//---MACROS
//	Desc:	passing of references as optional parameters
//----------------------------------------------------->
#define NULL_REFERENCE(type)				(*((type*)NULL))
#define VALID_REFERENCE(reference)		(&(reference) != NULL)
#define INVALID_REFERENCE(reference)	(&(reference) == NULL)
 
 
 
//---MACROS
//-------------------------------------------------------------------->
#define ARRAY_ITEMS(array)					(sizeof(array)/sizeof(array[0]))
#define ARRAY_BYTES(array)					(sizeof(array))
#define CAST(type,expression)				((type)(expression))
#define SEEAS(type,object)					(*(type*)(void*)&(object))
#define UNREFERENCED_PARAM(x)				(x)
 
#define ABS(a) ( (a)> 0  ? (a) : (-(a)) )
#define MIN(a,b) ( (a)<(b) ? (a) : (b) )
#define MAX(a,b) ( (a)>(b) ? (a) : (b) )
#define MAX3(a,b,c) (MAX(MAX(a,b),c))
#define MIN3(a,b,c) (MIN(MIN(a,b),c))
#define CLAMP(x,min,max) ((x) < (min)? (min) : ( (x) > (max) ? (max) : (x) ) )
 
 
 
//---EXCEPTION HANDLING
//--------------------->
#define BEGIN_TRY_BLOCK try{
#define BEGIN_CATCH_BLOCK(x) }catch(x){
#define END_CATCH_BLOCK }
 
 
 
//---INPLACE CONSTRUCTOR & DESTRUCTOR
//	Samp:	CONSTRUCT(Vector3,normal);
//			CONSTRUCT(Vector3,normal)(1,1,1);
//			DESTRUCT(Vector3,normal);
//	Note:	pointer conversion added to catch class mismatching
//---------------------------------------------------------->
#define CONSTRUCT(class,object) new ((class*)&(object)) class
#define DESTRUCT(class,object) (object).~class()
 
 
 
//---MACROS
//---------------->
#ifndef _WINERROR_
	typedef long HRESULT;
	#define SUCCEEDED(Status) ((HRESULT)(Status) >= 0)
	#define FAILED(Status) ((HRESULT)(Status)<0)
#endif
#define RS_SUCCESS 0x00000000
#define RS_FAILURE 0x80000000
#define RS_WARNING 0x00000001

 
 
 
 
namespace RSLib{
 
 
 
//---NEW OPERATOR
//	Desc: array new with non-default object construction.
//	Note:	C++ doesn't support non-default object construction in arrays.
//			we emulate it using templates with a byte allocation and in-place new.
//			destructors are correctly called as long as you use delete[] on a (T*)
//			since C++ doesn't store types within memory allocations.
//----------------------------------------------------------------------------->
template <typename T, typename U, typename A0> 
inline T* array_new(U count, A0& arg)
{
	T* p = (T*) new char[count * sizeof(T)];
	for(U i=0 ; i<count ; i++)	new(p+i) T(arg);
	return p;
}
template <typename T, typename U, typename A0, typename A1> 
inline T* array_new(U count, A0& arg0, A1& arg1)
{
	T* p = (T*) new char[count * sizeof(T)];
	for(U i=0 ; i<count ; i++)	new(p+i) T(arg0,arg1);
	return p;
}
template <typename T, typename U, typename A0, typename A1, typename A2> 
inline T* array_new(U count, A0& arg0, A1& arg1, A2& arg2)
{
	T* p = (T*) new char[count * sizeof(T)];
	for(U i=0 ; i<count ; i++)	new(p+i) T(arg0,arg1,arg2);
	return p;
}
 
 
 
template <typename T, typename U> T cast(U& in) {return (T)in;}
 
}//namespace RSLib
 
 
 
#endif//RSLIB___TYPES_HPP
